//=============================================================================
///	Stream
//=============================================================================

#ifndef	__STREAM_IFACE_H__
#define	__STREAM_IFACE_H__

#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

//=============================================================================
// Interface

typedef struct StreamBase StreamBase;

typedef struct {
	void (*close)(StreamBase* strm);
	int (*getc)(StreamBase* strm);
	void (*ungetc)(StreamBase* strm, int c);
	void (*puts)(StreamBase* strm, const char* str, int len);
	void (*flush)(StreamBase* strm);
} StreamVTbl;

// stream base class
struct StreamBase {
	const StreamVTbl* vtbl;
};

static __inline void close_stream(StreamBase* strm)					{ (strm->vtbl->close)(strm); }
static __inline int strm_getc(StreamBase* strm)						{ return (strm->vtbl->getc)(strm); }
static __inline void strm_ungetc(StreamBase* strm, int c)			{ (strm->vtbl->ungetc)(strm, c); }
static __inline void strm_puts(StreamBase* strm, const char* str, int len)	{ (strm->vtbl->puts)(strm, str, len); }


//=============================================================================
// File stream

typedef struct {
	StreamBase parent;
	FILE* fp;
} FileStream;

StreamBase* make_file_stream(FileStream* p, FILE* fp);

//=============================================================================
// String stream

typedef struct {
	StreamBase parent;
	const char* str;
	size_t len;
	const char* p;
} StringStream;

StreamBase* make_string_stream(StringStream* p, const char* str, size_t len);

//=============================================================================

#ifdef __cplusplus
} // extern "C"
#endif

#endif
